#!/usr/bin/env python
#
# Computes and reports statistical differences for job_stats files
#
# Author:   Mike Murphy <mamurph@cs.clemson.edu>
# Revision: 24 August 2009
#
#   Copyright 2009 Clemson University
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#
# This material is based upon work supported under a National Science
# Foundation Graduate Research Fellowship. Any opinions, findings,
# conclusions or recommendations expressed in this publication are those of
# the author(s) and do not necessarily reflect the views of the National
# Science Foundation.

import sqlite3, sys

SUFFIXES = ['mean_interarrival_time', 'stddev_interarrival_time', \
            'median_interarrival_time', 'min_interarrival_time', \
            'max_interarrival_time', 'mean_service_time', \
            'stddev_service_time', 'median_service_time', 'min_service_time', \
            'max_service_time', 'mean_sojourn_time', 'stddev_sojourn_time', \
            'median_sojourn_time', 'min_sojourn_time', 'max_sojourn_time', \
            'mean_wait_time', 'stddev_wait_time', 'median_wait_time', \
            'min_wait_time', 'max_wait_time', 'mean_arrival_rate', \
            'stddev_arrival_rate', 'median_arrival_rate', 'min_arrival_rate', \
            'max_arrival_rate']
#


if len(sys.argv) != 3:
   print >> sys.stderr, 'Usage:', sys.argv[0], '<from_sq3> <to_sq3>'
   sys.exit(2)
#

data = []
base = []
prefixed = []
only_lhs = []
only_rhs = []

for x in xrange(1,3):
   result = {}
   cxn = sqlite3.connect(sys.argv[x])
   cursor = cxn.cursor()
   cursor.execute('SELECT "measure", "value" FROM "Stats";')
   for row in cursor:
      result[row[0]] = row[1]
   cursor.close()
   cxn.close()
   data.append(result)
#

lhs = data[0]
rhs = data[1]

for key in lhs:
   if key in rhs:
      if key in SUFFIXES:
         base.append((key, lhs[key], rhs[key]))
      else:
         match = False
         for s in SUFFIXES:
            if key.endswith(s):
               prefixed.append((key, lhs[key], rhs[key]))
               match = True
               break
         if not match:
            base.append((key, lhs[key], rhs[key]))
      del rhs[key]
   else:
      only_lhs.append((key, lhs[key]))
#

for key in rhs:
   only_rhs.append((key, rhs[key]))
#

print 'FROM:', sys.argv[1]
print 'TO:  ', sys.argv[2]
print ''

def percent(x, y):
   r = '!'
   if y != 0:
      p = (float(x) / float(y)) * 100
      r = '%0.3f%%' % p
   return r
#

if len(base) > 0:
   base.sort(cmp=lambda a, b: cmp(a[0], b[0]))
   less = []
   greater = []
   equal = []
   for name, lv, rv in base:
      diff = rv - lv
      p = percent(diff, lv)
      rslt = '%s %0.3f <%s> (%0.3f -> %0.3f)' % (name, diff, p, lv, rv)
      if diff < 0:
         less.append(rslt)
      elif diff > 0:
         greater.append(rslt)
      else:
         equal.append(rslt)
   #
   if len(less) > 0:
      print '*** Base Decreases ***'
      for line in less:
         print line
      print ''
   if len(greater) > 0:
      print '*** Base Increases ***'
      for line in greater:
         print line
      print ''
   if len(equal) > 0:
      print '*** Base Unchanged ***'
      for line in equal:
         print line
      print ''
   print ''
#

lines = []
if len(prefixed) > 0:
   pf_map = {} # suffix: [total, less, greater, equal]
   for name, lv, rv in prefixed:
      key = ''
      for s in SUFFIXES:
         if name.endswith(s):
            key = s
            if key not in pf_map:
               pf_map[key] = [1, 0, 0, 0]
            else:
               pf_map[key][0] += 1
            break
      diff = rv - lv
      p = percent(diff, lv)
      if diff == 0:
         pf_map[key][3] += 1
      elif diff > 0:
         pf_map[key][2] += 1
      else:
         pf_map[key][1] += 1
      lines.append('%s %0.3f <%s> (%0.3f -> %0.3f)' % \
                   (name, diff, p, lv, rv))
   #
   print '*** VO summary ***'
   for s in SUFFIXES:
      if s in pf_map:
         t, l, g, e = pf_map[s]
         p = percent(l, t)
         print '%s decreased: %d <%s>' % (s, l, p)
         p = percent(g, t)
         print '%s increased: %d <%s>' % (s, g, p)
         p = percent(e, t)
         print '%s unchanged: %d <%s>' % (s, e, p)
   print ''
#

if len(only_lhs) > 0:
   print '*** Only in:', sys.argv[1], '***'
   for name, value in only_lhs:
      print '%s %0.3f' % (name, value)
   print ''
#

if len(only_rhs) > 0:
   print '*** Only in:', sys.argv[2], '***'
   for name, value in only_rhs:
      print '%s %0.3f' % (name, value)
   print ''
#

if len(lines) > 0:
   print '*** VO detail ***'
   for line in lines:
      print line
#
